﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using Steve.UI.Modules;
using Steve.UI.Models;

namespace Steve.UI.Controllers
{
    public abstract class ContentControllerBase : Controller
    {
        [Import]
        public ContentAdministrationRepository ContentAdministrationRepository { get; set; }
        [Import]
        public ContentRepository ContentRepository { get; set; }
        [Import]
        public ContentTypeRepository ContentTypeRepository { get; set; }
        [Import]
        public IAccountService Account { get; set; }
        [Import]
        public SiteExplorerRepository SiteExplorer { get; set; }
        [ImportMany(typeof(ContentDataHandlerBase))]
        public IEnumerable<Lazy<ContentDataHandlerBase, IDictionary<string, object>>> DataHandlers { get; set; }
        [Import]
        public ISearchQueryService Query { get; set; }

        public virtual ActionResult Search()
        {
            var model = new SearchModel();
            model.SearchType = SearchType.LatestApproved;
            return View("Search", model);
        }

        [HttpPost]
        [ActionName("Search")]
        public virtual ActionResult SearchPost(SearchModel model)
        {
            return View("Search", model);
        }

        [ChildActionOrHttpPost]
        public virtual ActionResult SearchResults(SearchModel model)
        {
            if (!ModelState.IsValid || model == null)
            {
                throw new HttpException(400, "Bad Request");
            }

            var result = Query.Search(model.SearchType, model.Query);

            return View("SearchResults", result);
        }

        [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "SteveSiteModule")]
        [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "SiteUrl")]
        [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ContentController")]
        [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
        public virtual ActionResult RenderUrl(bool approvedOnly = true, bool markRead = true)
        {
            var url = HttpContext.GetUrlMatch() as SiteUrl;
            if (url == null) throw new InvalidOperationException("The SteveSiteModule must set the current url for the ContentController and the current request must be a SiteUrl.");
            var c = ContentRepository.GetContentForSiteUrl(url.Id, approvedOnly);

            if (c == null) throw new HttpException(404, "File not found.");

            var ct = ContentTypeRepository.GetContentType(c.ContentTypeName);

            if (markRead) ContentAdministrationRepository.MarkContentRead(c.Id, null);

            return DataHandlers.Render(ct, c, false);
        }

        [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
        public virtual ActionResult Data(Guid id, int? revision = null, bool approvedOnly = true, bool raw = true, bool markRead = true)
        {
            var c = ContentRepository.GetContent(id, revision, approvedOnly);
            var ct = ContentTypeRepository.GetContentType(c.ContentTypeName);

            if (!raw && c.SiteUrlId != null)
            {
                //redirect if not a raw request and has a url
                return new PermanentRedirectResult(SiteExplorer.GetSiteUrl(c.SiteUrlId.Value).ToUri(SiteExplorer));
            }

            if (markRead) ContentAdministrationRepository.MarkContentRead(c.Id, null);

            return DataHandlers.Render(ct, c, raw);
        }

        [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
        [RouteValuePresent("id")]
        public virtual ActionResult SimilarContent(Guid id, string contentTypeName = null, bool approvedOnly = true, bool hideRead = true, int count = 10)
        {
            Guid? membershipId = null;

            if(hideRead)
            {
                var u = Account.GetUser();
                if(u != null) membershipId = (Guid)u.ProviderUserKey;
            }

            var similar = ContentRepository.GetContentSimilarToContent(id, approvedOnly, count, contentTypeName, membershipId);

            return View(similar);
        }

        [SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
        [RouteValueAbsent("id")]
        public virtual ActionResult SimilarContent(IEnumerable<string> requiredCategoryNames, IEnumerable<string> optionalCategoryNames, string contentTypeName = null, bool approvedOnly = true, bool hideRead = true, int count = 10)
        {
            Guid? membershipId = null;

            if (hideRead)
            {
                var u = Account.GetUser();
                if (u != null) membershipId = (Guid)u.ProviderUserKey;
            }

            var similar = ContentRepository.GetContentByCategories(requiredCategoryNames, optionalCategoryNames, true, approvedOnly, count, null, contentTypeName, membershipId);

            return View(similar);
        }

        [ChildActionOrHttpPost]
        public virtual ActionResult RateContent(Guid id, decimal rating)
        {
            ContentAdministrationRepository.MarkContentRead(id, rating);

            return new EmptyResult();
        }
    }
}
